package com.example.base.security;


import com.alibaba.fastjson.JSONObject;
import com.example.base.security.domain.SelfUserEntity;
import com.example.base.security.domain.SysRoleEntity;
import com.example.base.security.domain.SysUserEntity;
import com.example.base.security.service.SelfUserDetailsService;
import com.example.base.security.service.SysUserService;
import com.example.base.system.domain.SysLoginRecord;
import com.example.base.system.service.SysLoginRecordService;
import com.example.base.utils.RequestUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 自定义登录验证
 * @author Xiongx
 * @version 1.0
 * @date 2021/6/11 15:15
 * @since JDK 1.8
 */
@Slf4j
@Component
public class UserAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private SelfUserDetailsService selfUserDetailsService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysLoginRecordService sysLoginRecordService;

    @SneakyThrows
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        //登录请求体
        HttpServletRequest request=RequestUtils.getHttpServletRequest();
        if(request==null){
            throw new BadCredentialsException("错误的请求");
        }
        SysLoginRecord sysLoginRecord=new SysLoginRecord();
        String contentType=request.getContentType();
        String userName=null;
        String passWord=null;
        if("application/json".equals(contentType)){
            JSONObject jsonObject=RequestUtils.getJson(request);
            if(jsonObject!=null){
                userName=(String) jsonObject.get("username");
                passWord=(String) jsonObject.get("password");
            }
        }
        if(userName==null || passWord==null){
            userName = (String) authentication.getPrincipal();
            passWord=(String)authentication.getCredentials();
        }
        if(!StringUtils.isNotBlank(userName) || !StringUtils.isNotBlank(passWord)){
            throw new BadCredentialsException("账号或密码不得为空");
        }
        String ip=RequestUtils.getRemoteAddr(request);
        sysLoginRecord.setLoginIp(ip);
        sysLoginRecord.setLoginTime(new Date());
        sysLoginRecord.setUsername(userName);
        sysLoginRecord.setLoginType("system-api");
        sysLoginRecord.setCreatetime(new Date());

        String sessionId=request.getParameter("sessionId");
        log.info("sessionId {}",sessionId);

        log.info("username {}",userName);
        // 查询用户是否存在
        SelfUserEntity userInfo = selfUserDetailsService.loadUserByUsername(userName);
        if (userInfo == null) {
            sysLoginRecord.setLoginStatus(false);
            sysLoginRecord.setLoginNote("用户名不存在");
            sysLoginRecordService.saveSysLoginRecord(sysLoginRecord);
            throw new UsernameNotFoundException("用户名不存在");
        }
        sysLoginRecord.setUserId(userInfo.getUserId().toString());
        // 我们还要判断密码是否正确，这里我们的密码使用BCryptPasswordEncoder进行加密的
        if (!new BCryptPasswordEncoder().matches(passWord, userInfo.getPassword())) {
            sysLoginRecord.setLoginStatus(false);
            sysLoginRecord.setLoginNote("密码不正确");
            sysLoginRecordService.saveSysLoginRecord(sysLoginRecord);
            throw new BadCredentialsException("密码不正确");
        }
        // 还可以加一些其他信息的判断，比如用户账号已停用等判断
        if (userInfo.getStatus().equals("PROHIBIT")){
            sysLoginRecord.setLoginStatus(false);
            sysLoginRecord.setLoginNote("该用户已被冻结");
            sysLoginRecordService.saveSysLoginRecord(sysLoginRecord);
            throw new LockedException("该用户已被冻结");
        }
        // 角色集合
        Set<GrantedAuthority> authorities = new HashSet<>();
        // 查询用户角色
        List<SysRoleEntity> sysRoleEntityList = sysUserService.selectSysRoleByUserId(userInfo.getUserId());
        for (SysRoleEntity sysRoleEntity: sysRoleEntityList){
            authorities.add(new SimpleGrantedAuthority("ROLE_" + sysRoleEntity.getRoleno()));
        }
        userInfo.setAuthorities(authorities);
        sysLoginRecord.setLoginStatus(true);
        sysLoginRecord.setLoginNote("登录成功");
        sysLoginRecordService.saveSysLoginRecord(sysLoginRecord);

        SysUserEntity userEntity=new SysUserEntity();
        BeanUtils.copyProperties(userInfo,userEntity);
        // 进行登录
        return new UsernamePasswordAuthenticationToken(userEntity, passWord, authorities);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }




}
